home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJ111M1.ZIP / go32 / valloc.c < prev   
C/C++ Source or Header  |  1993-12-16  |  10KB  |  410 lines

  1. /* This is file VALLOC.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Bugs in large memory usage (both RAM & virtual) fixed Greg Galperin 2AUG93 */
  17.  
  18. /*
  19. Note: The functions here assume that memory is never really freed, just
  20. reused through page_out, unless we're exiting or running another
  21. program.  In either case, we don't need to keep track of what's freed
  22. since it's all going anyway.  Thus, vfree() is empty and the rest of the
  23. routines are relatively simple.  Note that VCPI may blow you up if you
  24. try to be clever in here. 
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <dos.h>
  31.  
  32. #include "gotypes.h"
  33. #include "valloc.h"
  34. #include "xms.h"
  35. #include "mono.h"
  36. #include "vcpi.h"
  37. #include "utils.h"
  38. #include "paging.h"
  39. #include "stubinfo.h"
  40. #include "proginfo.h"
  41. #include "control.h"
  42. #include "mswitch.h"
  43.  
  44. #define VA_FREE    0
  45. #define VA_USED    1
  46.  
  47. #define    DOS_PAGE 256        /*  1MB / 4KB = 256 Pages  */
  48.  
  49. extern char use_DPMI;
  50.  
  51. int valloc_initted = 0;
  52. static word8 map[4096];        /* Expanded/Extended paged, allocated with VA_1M */
  53.  
  54. word32 mem_avail, mem_used;    /* Kbytes */
  55.  
  56. static unsigned pn_lo_first, pn_lo_last, pn_hi_first, pn_hi_last;
  57. static unsigned pn_lo_next, pn_hi_next;
  58. static unsigned vcpi_flush_ok = 0;
  59. static char use_vcpi = 0;
  60.  
  61. extern int debug_mode;
  62. extern word16 vcpi_installed;    /* If VCPI is installed, set this not Zero  */
  63. extern word32 far *vcpi_pt;
  64.  
  65. void valloc_update_status(void)
  66. {
  67.   char buf[20];
  68.   int i;
  69.   if (!valloc_initted)
  70.     return;
  71.   sprintf(buf, "%6ldk", mem_avail);
  72.   for (i=0; i<7; i++)
  73.     poke(screen_seg, (i+70)*2, buf[i] | 0x0a00);
  74.   sprintf(buf, "%6ldk", mem_used);
  75.   for (i=0; i<7; i++)
  76.     poke(screen_seg, (i+62)*2, buf[i] | 0x0a00);
  77. }
  78.  
  79.  
  80. emb_handle_t emb_handle=-1;
  81.  
  82. void
  83. xms_free(void)
  84. {
  85.   if(use_xms && emb_handle != -1)
  86.   {
  87.     xms_unlock_emb(emb_handle);
  88.     xms_emb_free(emb_handle);
  89.     emb_handle = -1;
  90.   }
  91. }
  92.  
  93. void
  94. xms_alloc_init(void)
  95. {
  96.   xms_extended_info *x = xms_query_extended_memory();
  97.   emb_off_t linear_base;
  98.   emb_size_K_t emb_size;
  99.   emb_size = x->max_free_block;
  100.   emb_handle = xms_emb_allocate(emb_size);
  101.   linear_base = xms_lock_emb(emb_handle);
  102.   pn_hi_first = (word16)((linear_base + 4095)/4096);
  103.   pn_hi_last = (word16)((linear_base + emb_size * 1024L)/4096 - 1);
  104.   if (cpumode() && !vcpi_installed)
  105.   {
  106.     fprintf(stderr, "\nGo32 error: Using XMS switches the CPU into V86 mode.\n");
  107.     fprintf(stderr, "If you are using QEMM, add the `on' parameter to the entry\n");
  108.     fprintf(stderr, "in your CONFIG.SYS file.  See the FAQ for details.\n\n");
  109.     xms_free();
  110.     if (!show_memory_info)
  111.       exit(1);
  112.   }
  113. }
  114.  
  115.  
  116. static int valloc_lowmem_page;
  117. static unsigned lol;
  118.  
  119. void valloc_init(void)
  120. {
  121.   word32 left_lo, left_hi;
  122.   unsigned char far *vdisk;
  123.   int has_vdisk=1;
  124.   unsigned free_pages;
  125.   unsigned i;
  126.   struct REGPACK r;
  127.  
  128.   if (valloc_initted)
  129.     return;  
  130.  
  131.   if (vcpi_installed)
  132.   {
  133.     pn_hi_first = 0;
  134.     pn_hi_last  = vcpi_maxpage();
  135.     i = vcpi_capacity();
  136.     if ( i )
  137.     {
  138.       use_vcpi = 1;
  139.       if (show_memory_info)
  140.         fprintf(stderr, "VCPI (Expanded) memory available: %ld Kb\n", i * 4L);
  141.     }
  142.     else if(use_xms) 
  143.     {
  144.     xms_alloc_init();    /*  Try XMS allocation  */
  145.     if (show_memory_info)
  146.       fprintf(stderr, "XMS memory available: %ld Kb\n", ((word32)pn_hi_last-pn_hi_first) * 4);
  147.     }
  148.     prog_info.run_mode = _GO32_RUN_MODE_VCPI;
  149.   }
  150.   else if (use_xms)
  151.   {
  152.     xms_alloc_init();    /*  Try XMS allocation  */
  153.     if (show_memory_info)
  154.       fprintf(stderr, "XMS memory available: %ld Kb\n", ((word32)pn_hi_last-pn_hi_first) * 4);
  155.     prog_info.run_mode = _GO32_RUN_MODE_XMS;
  156.   }
  157.   else
  158.   {
  159.     /*
  160.     ** int 15/vdisk memory allocation
  161.     */
  162.     r.r_ax = 0x8800;    /* get extended memory size */
  163.     intr(0x15, &r);
  164.     pn_hi_last = r.r_ax / 4 + 255;
  165.  
  166.     /* get ivec 19h, seg only */
  167.     vdisk = (unsigned char far *)(*(long far *)0x64L & 0xFFFF0000L);
  168.     for (i=0; i<5; i++)
  169.     if (vdisk[i+18] != "VDISK"[i])
  170.       has_vdisk = 0;
  171.     if (has_vdisk)
  172.     {
  173.       pn_hi_first = ( (vdisk[46]<<4) | (vdisk[45]>>4) );
  174.       if (vdisk[44] | (vdisk[45]&0xf))
  175.         pn_hi_first ++;
  176.     }
  177.     else
  178.       pn_hi_first = 256;
  179.     if (show_memory_info)
  180.       fprintf(stderr, "Extended memory available: %ld Kb\n", ((word32)pn_hi_last-pn_hi_first) * 4);
  181.     prog_info.run_mode = _GO32_RUN_MODE_RAW;
  182.   }
  183.  
  184.   r.r_ax= 0x4800;    /* get real memory size */
  185.   r.r_bx = 0xffff;
  186.   intr(0x21, &r);    /* lol == size of largest free memory block */
  187.  
  188.   lol = r.r_bx;
  189. /*  printf("max pages is %u\n", lol); */
  190.   if (lol < 8*256)
  191.   {
  192.     fprintf(stderr, "Error: not enough memory to run go32!\n");
  193.     exit(1);
  194.   }
  195.  
  196.   free_pages = (unsigned)(stub_info.free_conventional_memory / 16);
  197. /*  printf("free pages desired is %u\n", free_pages); */
  198.   if (lol - 8*256 > free_pages)
  199.   {
  200.     lol -= free_pages;
  201. /*    printf("subtracting, lol now %u\n", lol); */
  202.   }
  203.   else
  204.   {
  205.     lol = 8*256;
  206. /*    printf("best we can do is %u\n", lol); */
  207.   }
  208.  
  209.   r.r_ax = 0x4800;
  210.   r.r_bx = lol;
  211. /*  printf("go32 uses %u para", lol); */
  212.   intr(0x21, &r);    /* get the block */
  213. /*  printf(" at %x, %d, %x\n", r.r_ax, r.r_flags, r.r_bx); */
  214.   pn_lo_first = (r.r_ax+0xFF) >> 8;    /* lowest real mem 4K block */
  215.   pn_lo_last = ((r.r_ax+lol-0x100)>>8);    /* highest real mem 4K block */
  216.   if (r.r_flags & 1)
  217.   {
  218.     fprintf(stderr, "Error: could not allocate memory for go32\n");
  219.     exit(1);
  220.   }
  221.  
  222.   valloc_lowmem_page = r.r_ax;
  223.  
  224.   pn_lo_next = pn_lo_first;
  225.   pn_hi_next = pn_hi_first;
  226.  
  227.   memset(map, 0, 4096);
  228.   vcpi_flush_ok = 1;
  229.  
  230.   mem_used = 0;
  231.   left_lo  = ((long)pn_lo_last - pn_lo_first + 1)*4;
  232.   left_hi  = (use_vcpi)? vcpi_capacity()*4:((long)pn_hi_last-pn_hi_first+1)*4;
  233.   mem_avail = left_lo + left_hi;
  234.  
  235.   if (debug_mode)
  236.     fprintf(stderr, "%ld Kb conventional, %ld Kb %s - %ld Kb total RAM available\n",
  237.       left_lo, left_hi,
  238.       use_DPMI ? "dpmi" : use_vcpi ? "expanded" : use_xms ? "XMS" : "extended",
  239.       mem_avail);
  240.  
  241.   if (topline_info)
  242.     valloc_update_status();
  243.  
  244.   valloc_initted = 1;
  245. }
  246.  
  247. void valloc_shrink_rmem(int pages)
  248. {
  249.   if (pn_lo_last - pn_lo_next > pages)
  250.   {
  251.     struct REGPACK r;
  252. /*    printf("Changing allocation down %d pages from %d ", pages, lol); */
  253.     lol -= pages * 256;
  254.     r.r_ax = 0x4a00;    /* modify real memory size */
  255.     r.r_bx = lol;
  256.     r.r_es = valloc_lowmem_page;
  257. /*    printf("to %d (0x%04x)\n", lol, valloc_lowmem_page); */
  258.     intr(0x21, &r);
  259.   }
  260. /*  else
  261.   {
  262.     printf("most avail pages is %d (wanted %d)\n", pn_lo_last - pn_lo_next, pages);
  263.   } */
  264. }
  265.  
  266. void valloc_uninit(void)
  267. {
  268.   struct REGPACK r;
  269.   if (!valloc_initted)
  270.     return;
  271.  
  272.   r.r_es = valloc_lowmem_page;    /* free the block we allocated */
  273.   r.r_ax = 0x4900;
  274.   intr(0x21, &r);
  275.  
  276.   xms_free();
  277.   valloc_initted = 0;
  278. }
  279.  
  280. unsigned valloc(where)
  281. {
  282.   unsigned pn;
  283.   if (!valloc_initted)
  284.     valloc_init();
  285.   switch (where)
  286.   {
  287.     case VA_640:
  288.       if (pn_lo_next <= pn_lo_last)
  289.       {
  290.         mem_avail -= 4;
  291.         mem_used += 4;
  292.         if (topline_info)
  293.           valloc_update_status();
  294.         return pn_lo_next++;
  295.       }
  296.  
  297.       pn = page_out(VA_640);
  298.       if (pn != 0xffff)
  299.       {
  300.         return pn;
  301.       }
  302.       fprintf(stderr, "Error: out of conventional memory\n");
  303.       exit(1);
  304.     case VA_1M:
  305.       if (use_vcpi)
  306.       {
  307.     if ((pn = vcpi_alloc()) != 0)
  308.     {
  309.           mem_avail -= 4;
  310.           mem_used += 4;
  311.           if (topline_info)
  312.             valloc_update_status();
  313.       map[pn>>3] |= 1 << (pn&7);
  314.       return pn;
  315.     }
  316.       }
  317.       else
  318.       {
  319.         if (pn_hi_next <= pn_hi_last)
  320.         {
  321.           mem_avail -= 4;
  322.           mem_used += 4;
  323.           if (topline_info)
  324.             valloc_update_status();
  325.       return pn_hi_next++;
  326.     }
  327.       }
  328.       /* Difference is -1 when there are no pages left, so
  329.          use signed compare. */
  330.       if ((signed)pn_lo_last-(signed)pn_lo_next > 3) /* save last four for VA_640 */
  331.       {
  332.         mem_avail -= 4;
  333.         mem_used += 4;
  334.         if (topline_info)
  335.           valloc_update_status();
  336.         return (word16)(vcpi_pt[pn_lo_next++] >> 12);
  337.       }
  338.  
  339.       pn = page_out(VA_1M);
  340.       if (pn != 0xffff)
  341.       {
  342.         return pn;
  343.       }
  344.       fprintf(stderr, "Error: out of extended memory\n");
  345.       exit(1);
  346.   }
  347.   return 0;
  348. }
  349.  
  350. void vfree_640()
  351. {
  352.   struct REGPACK r;
  353.  
  354.   r.r_es = valloc_lowmem_page;    /* free the block we allocated */
  355.   r.r_ax = 0x4900;
  356.   intr(0x21, &r);
  357. }
  358.  
  359. void vrecover_640()
  360. {
  361.   struct REGPACK r;
  362.  
  363.   r.r_ax= 0x4800;    /* get real memory size */
  364.   r.r_bx = 0xffff;
  365.   intr(0x21, &r);    /* lol == size of largest free memory block */
  366.  
  367.   if (lol != r.r_bx)
  368.   {
  369.     fprintf(stderr, "Error: unable to realloc conventional memory (wrong size)\n");
  370.     exit(1);
  371.   }
  372.   r.r_ax = 0x4800;
  373.   intr(0x21, &r);    /* get the block */
  374.   if (r.r_ax != valloc_lowmem_page)
  375.   {
  376.     fprintf(stderr, "Error: unable to realloc conventional memory (wrong address)\n");
  377.     exit(1);
  378.   }
  379.   pn_lo_next = pn_lo_first;
  380. }
  381.  
  382. void vfree(void)
  383. {
  384.   mem_avail += 4;
  385.   mem_used -= 4;
  386.   if (topline_info)
  387.     valloc_update_status();
  388. }
  389.  
  390. void vcpi_flush(void)        /* only called on exit */
  391. {
  392.   word16 pn;
  393.  
  394.   if (!vcpi_flush_ok || !use_vcpi)
  395.     return;            /*  Not Initaialized Map[]  */
  396.   for(pn = pn_hi_first; pn <= pn_hi_last; pn++)
  397.     if (map[pn>>3] & (1 << (pn&7)))
  398.       vcpi_free(pn);
  399. }
  400.  
  401. unsigned valloc_max_size(void)
  402. {
  403.   return (unsigned)((mem_avail + mem_used) / 4);
  404. }
  405.  
  406. unsigned valloc_used(void)
  407. {
  408.   return (unsigned)(mem_used / 4);
  409. }
  410.